﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Slwy.Utility.Extensions;

namespace Slwy.JwtAuth
{
    /// <summary>
    /// 参数加签
    /// 签名规则
    /// 1、对接收的Json/Url参数转换成字段键值对；
    /// 2、对字典Key按字母进行排序；
    /// 3、取出字段Value值进行Md5组装成sign_type
    /// 4、加上time_stamp值
    /// </summary>
    public static class SignEncrypt
    {
        /// <summary>
        /// MD5Key
        /// </summary>
        private static readonly string privateKey = "9FC4622CCDE74A87D05824C7E7CADD3BQA";

        public static IDictionary<string, object> SignEncryptModel<T>(T model)
        {
            var dic = model.ToJson().FromJson<Dictionary<string, object>>();
            if (!dic.ContainsKey("Timestamp"))
            {
                dic.Add("Timestamp", DateTime.Now.ToString("yyyyMMddHHmmss"));
            }
            var signMd5 = SignMd5(dic);

            if (!dic.ContainsKey("sign_type"))
            {
                dic.Add("sign_type", signMd5);
            }

            return dic;
        }

        /// <summary>
        /// 返回加签的Json数据.
        /// </summary>
        /// <param name="jsonParam">The json parameter.</param>
        /// <returns></returns>
        public static string SignEncryptJson(string jsonParam)
        {
            Dictionary<string, object> dic = ParamConvert.JsonToDic(jsonParam);
            //  SortedDictionary<string, object> sortedDic = ParamConvert.JsonToDic(jsonParam);
            // 对排序后所有参数值加密生成sign,去掉空值
            string signMd5 = SignMd5(dic);
            if (!dic.ContainsKey("sign_type"))
            {
                dic.Add("sign_type", signMd5);
            }

            string json = JsonConvert.SerializeObject(dic);
            return json;
        }

        /// <summary>
        /// 返回加签后url，如格式a=1&b=2&times_tamp=201704120906sign_type=ER55TG9FC4622CCDE74A87D05824C7E7CADD3BQAHYJKL.
        /// </summary>
        /// <param name="urlParam">The URL parameter.</param>
        /// <returns></returns>
        public static string SignEncryptUrl(string urlParam)
        {
            Dictionary<string, object> dic = ParamConvert.JsonToDic(urlParam);
            string signMd5 = SignMd5(dic);
            dic.Add("sign_type", signMd5);
            return ParamConvert.CreateLinkString(dic);
        }

        /// <summary>
        /// 验签操作
        /// </summary>
        /// <param name="param">The parameter.</param>
        /// <returns></returns>
        public static bool SignValidate(string param)
        {
            Dictionary<string, object> dic = ParamConvert.JsonToDic(param);
            if (dic["sign_type"] == null)
            {
                throw new Exception("请检测签名sign_type是否存在");
            }

            string sign_type = dic["sign_type"].ToString();
            Dictionary<string, object> convertDic = new Dictionary<string, object>();
            //foreach (var item in dic)
            //{
            //    convertDic[item.Key] = HttpUtility.UrlDecode(item.Value.ToString(), Encoding.UTF8);
            //}

            string signMd5 = SignMd5(dic);
            if (sign_type == signMd5)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        ///对字典里数据加密.
        /// </summary>
        /// <param name="dic">The sorted dic.</param>
        /// <returns></returns>
        static string SignMd5(Dictionary<string, object> dic)
        {
            // 1、字典参数排序
            SortedDictionary<string, object> sortedDic = ParamConvert.FilterPara(dic);
            StringBuilder strBuild = new StringBuilder();
            foreach (var item in sortedDic)
            {
                // 2、排除掉sign_type 且值不能为空
                if (item.Key != "sign_type" && item.Value != null && !string.IsNullOrWhiteSpace(item.Value.ToString()))
                {
                    // 3、 对值进行Base64编码
                    string value = item.Value.ToString().Replace("\r\n", "");
                    value = Regex.Replace(value, @"\s", "");
                    byte[] dataBytes = Encoding.GetEncoding("utf-8").GetBytes(value);
                    string strBase64 = Convert.ToBase64String(dataBytes);
                    strBuild.Append(strBase64);

                }
            }

            // 4、所有的Value值与MD5 Key值相加
            strBuild.Append(privateKey);

            // 5、Md5加密
            string sign = strBuild.ToString().GetMD5();
            return sign;
        }
    }
}
